home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / mach / sun4.md / machAsmDefs.h < prev    next >
C/C++ Source or Header  |  1990-01-31  |  14KB  |  463 lines

  1. /*
  2.  * machAsmDefs.h --
  3.  *
  4.  *     Machine-dependent macros.
  5.  *
  6.  * Copyright (C) 1985 Regents of the University of California
  7.  * All rights reserved.
  8.  *
  9.  *
  10.  * $Header: /sprite/src/kernel/mach/sun4.md/RCS/machAsmDefs.h,v 9.2 90/01/31 18:08:03 mgbaker Exp $ SPRITE (Berkeley)
  11.  */
  12.  
  13. #ifndef _MACHASMDEFS
  14. #define _MACHASMDEFS
  15.  
  16. #ifdef KERNEL
  17. #include "vmSunConst.h"
  18. #include "machConst.h"
  19. #else
  20. #include <kernel/vmSunConst.h>
  21. #include <kernel/machConst.h>
  22. #endif
  23.  
  24. /*
  25.  * Wait the 3 instructions necessary to allow a newly-written state register
  26.  * to settle.
  27.  */
  28. #define    MACH_WAIT_FOR_STATE_REGISTER()            \
  29.     nop;                        \
  30.     nop;                        \
  31.     nop
  32. /*
  33.  * Bump the invalid window forward one.  This is done by changing the
  34.  * invalid window mask.  We shift the invalid window bit left by 1,
  35.  * but modulo the number of implemented windows.
  36.  */
  37. #define    MACH_ADVANCE_WIM(REG1, REG2)            \
  38.     mov    %wim, REG1;                \
  39.     srl    REG1, 0x1, REG2;            \
  40.     sll    REG1, (MACH_NUM_WINDOWS - 1), REG1;    \
  41.     or    REG1, REG2, REG1;            \
  42.     set    MACH_VALID_WIM_BITS, REG2;        \
  43.     and    REG1, REG2, REG1;            \
  44.     mov    REG1, %wim;                \
  45.     MACH_WAIT_FOR_STATE_REGISTER()
  46.  
  47. /*
  48.  * Set the window invalid mask to point to the current window.
  49.  */
  50. #define    MACH_SET_WIM_TO_CWP()                    \
  51.     mov    %psr, %VOL_TEMP1;                \
  52.     and    %VOL_TEMP1, MACH_CWP_BITS, %VOL_TEMP1;        \
  53.     set    0x1, %VOL_TEMP2;                \
  54.     sll    %VOL_TEMP2, %VOL_TEMP1, %VOL_TEMP1;        \
  55.     mov    %VOL_TEMP1, %wim;                \
  56.     MACH_WAIT_FOR_STATE_REGISTER()
  57.  
  58. /*
  59.  * Move the invalid window backwards one.  This is done by changing the
  60.  * invalid window mask.  We shift the invalid window bit right by 1,
  61.  * but modulo the number of implemented windows.
  62.  */
  63. #define    MACH_RETREAT_WIM(REG1, REG2, happyWindow)    \
  64.     mov    %wim, REG1;                \
  65.     sll    REG1, 0x1, REG1;            \
  66.     set    MACH_VALID_WIM_BITS, REG2;        \
  67.     andcc    REG2, REG1, REG1;            \
  68.     bne    happyWindow;                \
  69.     nop;                        \
  70.     mov    0x1, REG1;                \
  71. happyWindow:                        \
  72.     mov    REG1, %wim;                \
  73.     MACH_WAIT_FOR_STATE_REGISTER()
  74.  
  75. /*
  76.  * Test whether we're in an invalid window.  If we are in an invalid window,
  77.  * then the condition codes should indicate a not zero ("bne" instruction
  78.  * will branch).
  79.  */
  80. #define    MACH_INVALID_WINDOW_TEST()                \
  81.     mov    %psr, %VOL_TEMP1;                \
  82.     and    %VOL_TEMP1, MACH_CWP_BITS, %VOL_TEMP1;        \
  83.     set    0x1, %VOL_TEMP2;                \
  84.     sll    %VOL_TEMP2, %VOL_TEMP1, %VOL_TEMP1;        \
  85.     mov    %wim, %VOL_TEMP2;                \
  86.     andcc    %VOL_TEMP1, %VOL_TEMP2, %g0
  87.  
  88. /*
  89.  * Test whether we're about to encounter a window underflow condition.
  90.  * We put current cwp into temp1.  We shift a one by that many bits.
  91.  * Then we shift it again, to "advance" the window by one.  We and it
  92.  * with the valid window bits to get it modulo the number of windows - 1.
  93.  * Then we compare it with current wim to see if they're the same.  If
  94.  * so, then we would get an underflow if we did a restore operation.
  95.  * If we are in an underflow situation, then the condition codes should
  96.  * indicate a not zero ("bne" instruction will branch).
  97.  */
  98. #define    MACH_UNDERFLOW_TEST(moduloOkay)                \
  99.     mov    %psr, %VOL_TEMP1;                \
  100.     and    %VOL_TEMP1, MACH_CWP_BITS, %VOL_TEMP1;        \
  101.     set    0x1, %VOL_TEMP2;                \
  102.     sll    %VOL_TEMP2, %VOL_TEMP1, %VOL_TEMP1;        \
  103.     sll    %VOL_TEMP1, 0x1, %VOL_TEMP1;            \
  104.     set    MACH_VALID_WIM_BITS, %VOL_TEMP2;        \
  105.     andcc    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1;        \
  106.     bne    moduloOkay;                    \
  107.     nop;                            \
  108.     mov    0x1, %VOL_TEMP1;                \
  109. moduloOkay:                            \
  110.     mov    %wim, %VOL_TEMP2;                \
  111.     andcc    %VOL_TEMP1, %VOL_TEMP2, %g0
  112.  
  113. /*
  114.  * The sequence we need to go through to restore the psr without restoring
  115.  * the old current window number.  We want to remain in our current window.
  116.  * 1) Get old psr.  2) Clear only its cwp bits.  3) Get current psr.
  117.  * 4) Grab only its cwp bits.  5) Stick the two together and put it in
  118.  * the psr reg.  6) Wait for the register to be valid.
  119.  */
  120. #define    MACH_RESTORE_PSR()                    \
  121.     mov    %CUR_PSR_REG, %VOL_TEMP2;            \
  122.     set     (~MACH_CWP_BITS), %VOL_TEMP1;            \
  123.     and     %VOL_TEMP2, %VOL_TEMP1, %VOL_TEMP2;        \
  124.     mov     %psr, %VOL_TEMP1;                \
  125.     and     %VOL_TEMP1, MACH_CWP_BITS, %VOL_TEMP1;        \
  126.     or      %VOL_TEMP2, %VOL_TEMP1, %VOL_TEMP2;        \
  127.     mov     %VOL_TEMP2, %psr;                \
  128.     MACH_WAIT_FOR_STATE_REGISTER()
  129.     
  130.  
  131. /*
  132.  * Save global registers.
  133.  * Store-doubles are faster and we do this from even register boundaries.
  134.  * For now, we only save the globals here, since the locals and ins will
  135.  * be saved on normal save-window operations.  Note that this means the
  136.  * stack pointer and MACH_GLOBALS_OFFSET must be double-word aligned.
  137.  */
  138. #define    MACH_SAVE_GLOBAL_STATE()                \
  139.     add    %sp, MACH_GLOBALS_OFFSET, %VOL_TEMP1;        \
  140.     std    %g0, [%VOL_TEMP1];                \
  141.     std    %g2, [%VOL_TEMP1 + 8];                \
  142.     std    %g4, [%VOL_TEMP1 + 16];                \
  143.     std    %g6, [%VOL_TEMP1 + 24]
  144.  
  145. /*
  146.  * Restore the global registers.  We do load doubles here for speed
  147.  * for even-register boundaries.  For now, we only restore the globals
  148.  * from here, since the locals and ins will be restored as part of the
  149.  * normal restore window operations.  Note that this means the stack pointer
  150.  * and MACH_GLOBALS_OFFSET must be double-word aligned.
  151.  */
  152. #define    MACH_RESTORE_GLOBAL_STATE()                \
  153.     add    %sp, MACH_GLOBALS_OFFSET, %VOL_TEMP1;        \
  154.     ldd    [%VOL_TEMP1], %g0;                \
  155.     ldd    [%VOL_TEMP1 + 8], %g2;                \
  156.     ldd    [%VOL_TEMP1 + 16], %g4;                \
  157.     ldd    [%VOL_TEMP1 + 24], %g6
  158.  
  159. /*
  160.  * Save r16 to r23 (locals) and r24 to r31 (ins) to 16 words at
  161.  * the top of this window's stack.
  162.  */
  163. #define    MACH_SAVE_WINDOW_TO_STACK()            \
  164.     std    %r16, [%sp];                \
  165.     std    %r18, [%sp + 8];            \
  166.     std    %r20, [%sp + 16];            \
  167.     std    %r22, [%sp + 24];            \
  168.     std    %r24, [%sp + 32];            \
  169.     std    %r26, [%sp + 40];            \
  170.     std    %r28, [%sp + 48];            \
  171.     std    %r30, [%sp + 56]
  172.  
  173. #define    MACH_RESTORE_WINDOW_FROM_STACK()        \
  174.     ldd    [%sp], %r16;                \
  175.     ldd    [%sp + 8], %r18;            \
  176.     ldd    [%sp + 16], %r20;            \
  177.     ldd    [%sp + 24], %r22;            \
  178.     ldd    [%sp + 32], %r24;            \
  179.     ldd    [%sp + 40], %r26;            \
  180.     ldd    [%sp + 48], %r28;            \
  181.     ldd    [%sp + 56], %r30
  182.  
  183. #define    MACH_SAVE_WINDOW_TO_BUFFER(reg1)        \
  184.     std    %r16, [reg1];                \
  185.     std    %r18, [reg1 + 8];            \
  186.     std    %r20, [reg1 + 16];            \
  187.     std    %r22, [reg1 + 24];            \
  188.     std    %r24, [reg1 + 32];            \
  189.     std    %r26, [reg1 + 40];            \
  190.     std    %r28, [reg1 + 48];            \
  191.     std    %r30, [reg1 + 56]
  192.  
  193.  
  194. /*
  195.  * Clear out the local and out registers for a new window to move into
  196.  * or a window we're moving out of.
  197.  * Outs: r8 to r15, locals: r16 to r23.
  198.  */
  199. #define    MACH_CLEAR_WINDOW()                \
  200.     clr    %r8;                    \
  201.     clr    %r9;                    \
  202.     clr    %r10;                    \
  203.     clr    %r11;                    \
  204.     clr    %r12;                    \
  205.     clr    %r13;                    \
  206.     clr    %r14;                    \
  207.     clr    %r15;                    \
  208.     clr    %r16;                    \
  209.     clr    %r17;                    \
  210.     clr    %r18;                    \
  211.     clr    %r19;                    \
  212.     clr    %r20;                    \
  213.     clr    %r21;                    \
  214.     clr    %r22;                    \
  215.     clr    %r23
  216.  
  217. /*
  218.  * Enabling and disabling traps.
  219.  */
  220. #define    MACH_ENABLE_TRAPS(useReg)            \
  221.     mov    %psr, useReg;                \
  222.     or    useReg, MACH_ENABLE_TRAP_BIT, useReg;    \
  223.     mov    useReg, %psr;                \
  224.     MACH_WAIT_FOR_STATE_REGISTER()
  225.  
  226. /*
  227.  * Should I use xor here and MACH_ENABLE_TRAP_BIT?
  228.  */
  229. #define    MACH_DISABLE_TRAPS(useReg1, useReg2)        \
  230.     mov    %psr, useReg1;                \
  231.     set    MACH_DISABLE_TRAP_BIT, useReg2;        \
  232.     and    useReg1, useReg2, useReg1;        \
  233.     mov    useReg1, %psr;                \
  234.     MACH_WAIT_FOR_STATE_REGISTER()
  235.  
  236. /*
  237.  * Equivalents to C macros for enabling and disabling interrupts.
  238.  * They aren't quite equivalent, since they don't do panic's on negative
  239.  * disable counts.  These macros should really only be used for debugging,
  240.  * in any case.
  241.  */
  242. #define    DISABLE_INTR_ASM(reg1, reg2, NoDisableLabel)    \
  243.     set    _mach_AtInterruptLevel, reg1;    \
  244.     ld    [reg1], reg1;            \
  245.     tst    reg1;                \
  246.     bne    NoDisableLabel;            \
  247.     nop;                    \
  248.     mov    %psr, reg1;            \
  249.     set    MACH_DISABLE_INTR, reg2;    \
  250.     or    reg1, reg2, reg1;        \
  251.     mov    reg1, %psr;            \
  252.     MACH_WAIT_FOR_STATE_REGISTER();        \
  253.     set    _mach_NumDisableIntrsPtr, reg1;    \
  254.     ld    [reg1], reg2;            \
  255.     add    reg2, 0x1, reg2;        \
  256.     st    reg2, [reg1];            \
  257. NoDisableLabel:
  258.  
  259. #define    ENABLE_INTR_ASM(reg1, reg2, NoEnableLabel)    \
  260.     set    _mach_AtInterruptLevel, reg1;    \
  261.     ld    [reg1], reg1;            \
  262.     tst    reg1;                \
  263.     bne    NoEnableLabel;            \
  264.     nop;                    \
  265.     set    _mach_NumDisableIntrsPtr, reg1;    \
  266.     ld    [reg1], reg2;            \
  267.     sub    reg2, 0x1, reg2;        \
  268.     st    reg2, [reg1];            \
  269.     tst    reg2;                \
  270.     bne    NoEnableLabel;            \
  271.     nop;                    \
  272.     mov    %psr, reg1;            \
  273.     set    MACH_ENABLE_INTR, reg2;        \
  274.     and    reg1, reg2, reg1;        \
  275.     mov    reg1, %psr;            \
  276.     MACH_WAIT_FOR_STATE_REGISTER();        \
  277. NoEnableLabel:
  278.  
  279. /*
  280.  * Enable interrupts and keep traps enabled.
  281.  * Uses given register.
  282.  */
  283. #define    QUICK_ENABLE_INTR(reg)                \
  284.     mov    %psr, reg;                \
  285.     andn    reg, MACH_DISABLE_INTR, reg;        \
  286.     mov    reg, %psr;                \
  287.     MACH_WAIT_FOR_STATE_REGISTER()
  288.  
  289. /*
  290.  * Disable interrupts and keep traps enabled.
  291.  * Uses given register.
  292.  */
  293. #define    QUICK_DISABLE_INTR(reg)                \
  294.     mov    %psr, reg;                \
  295.     or    reg, MACH_DISABLE_INTR, reg;        \
  296.     mov    reg, %psr;                \
  297.     MACH_WAIT_FOR_STATE_REGISTER()
  298.  
  299. /*
  300.  * Set interrupts to a particular value.  This is useful for a routine that
  301.  * just wants to save the value, change it, and then reset it without worrying
  302.  * about whether this turns interrupts on or off.
  303.  */
  304. #define    SET_INTRS_TO(regValue, useReg1, useReg2)        \
  305.     mov    %psr, useReg1;                    \
  306.     set    MACH_ENABLE_INTR, useReg2;            \
  307.     and    useReg1, useReg2, useReg1;            \
  308.     set    MACH_DISABLE_INTR, useReg2;            \
  309.     and    regValue, useReg2, useReg2;            \
  310.     or    useReg1, useReg2, useReg1;            \
  311.     mov    useReg1, %psr;                    \
  312.     MACH_WAIT_FOR_STATE_REGISTER()
  313.  
  314. /*
  315.  * Run at high priority: supervisor mode, interrupts disabled, traps enabled.
  316.  * This must be done in 2 steps - 1) leaving traps off, if they were off,
  317.  * set new interrupt level.  2) Enable traps.  This keeps us from getting
  318.  * an interrupt at the old level rather than the new right after enabling
  319.  * traps.
  320.  */
  321. #define    MACH_SR_HIGHPRIO()                    \
  322.     mov    %psr, %VOL_TEMP1;                \
  323.     set    (MACH_DISABLE_INTR | MACH_SUPER_BIT), %VOL_TEMP2;    \
  324.     or    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1;        \
  325.     mov    %VOL_TEMP1, %psr;                \
  326.     or    %VOL_TEMP1, MACH_ENABLE_TRAP_BIT, %VOL_TEMP1;    \
  327.     mov    %VOL_TEMP1, %psr;                \
  328.     MACH_WAIT_FOR_STATE_REGISTER()
  329.  
  330. /*
  331.  * Run at low supervisor priority: supervisor mode, interrupts enabled, traps
  332.  * enabled.  As described above for MACH_SR_HIGHPRIO, we must do this in
  333.  * 2 steps.
  334.  */
  335. #define    MACH_SR_LOWPRIO()                    \
  336.     mov    %psr, %VOL_TEMP1;                \
  337.     set    MACH_SUPER_BIT, %VOL_TEMP2;            \
  338.     or    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1;        \
  339.     set    MACH_ENABLE_INTR, %VOL_TEMP2;            \
  340.     and    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1;        \
  341.     mov    %VOL_TEMP1, %psr;                \
  342.     or    %VOL_TEMP1, MACH_ENABLE_TRAP_BIT, %VOL_TEMP2;    \
  343.     mov    %VOL_TEMP1, %psr;                \
  344.     MACH_WAIT_FOR_STATE_REGISTER()
  345. /*
  346.  * Run at user priority: user mode, traps on.
  347.  */
  348. #define    MACH_SR_USERPRIO()                    \
  349.     mov    %psr, %VOL_TEMP1;                \
  350.     set    MACH_ENABLE_TRAP_BIT, %VOL_TEMP2;        \
  351.     or    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1;        \
  352.     set    (~MACH_SUPER_BIT), %VOL_TEMP2;            \
  353.     and    %VOL_TEMP1, %VOL_TEMP2, %VOL_TEMP1;        \
  354.     mov    %VOL_TEMP1, %psr;                \
  355.     MACH_WAIT_FOR_STATE_REGISTER()
  356.  
  357.  
  358. /*
  359.  * For sticking debug info into a buffer.  After each value, stamp a special
  360.  * mark, which gets overwritten by the next value, so we always know where
  361.  * the end of the list is.
  362.  */
  363. #define    MACH_DEBUG_BUF(reg1, reg2, DebugLabel, stuff)    \
  364.     set    _debugCounter, reg1;         \
  365.     ld    [reg1], reg1;            \
  366.     sll    reg1, 2, reg1;            \
  367.     set    _debugSpace, reg2;        \
  368.     add    reg2, reg1, reg2;        \
  369.     st    stuff, [reg2];            \
  370.     set    _debugCounter, reg1;        \
  371.     ld    [reg1], reg1;            \
  372.     add    reg1, 1, reg1;            \
  373.     set    500, reg2;            \
  374.     subcc    reg2, reg1, %g0;        \
  375.     bgu    DebugLabel;            \
  376.     nop;                    \
  377.     clr    reg1;                \
  378. DebugLabel:                    \
  379.     set    _debugCounter, reg2;        \
  380.     st    reg1, [reg2];            \
  381.     sll    reg1, 2, reg1;            \
  382.     set    _debugSpace, reg2;        \
  383.     add    reg2, reg1, reg2;        \
  384.     set    0x11100111, reg1;        \
  385.     st    reg1, [reg2]
  386.  
  387. #define    MACH_DEBUG_ONCE(reg1, reg2, NoMoreLabel, DebugLabel, stuff, a_num)\
  388.     set    _debugCounter, reg1;        \
  389.     ld    [reg1], reg1;            \
  390.     cmp    reg1, a_num;            \
  391.     bg    NoMoreLabel;            \
  392.     nop;                    \
  393.     MACH_DEBUG_BUF(reg1, reg2, DebugLabel, stuff);    \
  394. NoMoreLabel:                    \
  395.     nop
  396.  
  397. /*
  398.  * This is the equivalent to a call to VmmachGetPage followed by a test on
  399.  * the returned pte to see if it is resident and user readable and writable.
  400.  * This is used where a call to the vm code won't work since output registers
  401.  * aren't available.  This sets the condition codes so that 0 is returned
  402.  * if the address is resident and not protected and not zero is returned if
  403.  * a fault would occur.
  404.  */
  405. #define    MACH_CHECK_FOR_FAULT(checkReg, reg1)    \
  406.     set    VMMACH_PAGE_MAP_MASK, reg1;        \
  407.     and    checkReg, reg1, reg1;            \
  408.     lda    [reg1] VMMACH_PAGE_MAP_SPACE, reg1;    \
  409.     srl    reg1, VMMACH_PAGE_PROT_SHIFT, reg1;    \
  410.     cmp    reg1, VMMACH_PTE_OKAY_VALUE
  411.  
  412. /*
  413.  * This is similar to the above macro, except that it is intended for checking
  414.  * stack pointers to see if a restore of a window would page fault.  We check
  415.  * the value of the stack pointer, and the offset of the window size.
  416.  */
  417. #define MACH_CHECK_STACK_FAULT(checkReg, reg1, ansReg, reg2, TestAgainLabel, LastOKLabel)    \
  418.     clr    ansReg;                    \
  419.     set    VMMACH_PAGE_MAP_MASK, reg1;        \
  420.     and    checkReg, reg1, reg1;            \
  421.     lda    [reg1] VMMACH_PAGE_MAP_SPACE, reg1;    \
  422.     srl    reg1, VMMACH_PAGE_PROT_SHIFT, reg1;    \
  423.     cmp    reg1, VMMACH_PTE_OKAY_VALUE;        \
  424.     be    TestAgainLabel;                \
  425.     nop;                        \
  426.     set    0x2, ansReg;                \
  427. TestAgainLabel:                        \
  428.     set    VMMACH_PAGE_MAP_MASK, reg1;        \
  429.     add    checkReg, (MACH_SAVED_WINDOW_SIZE - 4), reg2;    \
  430.     and    reg2, reg1, reg1;            \
  431.     lda    [reg1] VMMACH_PAGE_MAP_SPACE, reg1;    \
  432.     srl    reg1, VMMACH_PAGE_PROT_SHIFT, reg1;    \
  433.     cmp    reg1, VMMACH_PTE_OKAY_VALUE;        \
  434.     be    LastOKLabel;                \
  435.     nop;                        \
  436.     or    ansReg, 0x4, ansReg;            \
  437. LastOKLabel:                        \
  438.     tst    ansReg
  439.     
  440.     
  441.  
  442.  
  443. /*
  444.  * Get a ptr to the pcb structure of the current process.
  445.  * Return this in reg1
  446.  */
  447. #define    MACH_GET_CUR_PROC_PTR(reg1)            \
  448.     set    _proc_RunningProcesses, reg1;        \
  449.     ld    [reg1], reg1;                \
  450.     ld    [reg1], reg1
  451.  
  452. /*
  453.  * Get a ptr to the Mach_State struct of the current process.  Put it in reg1.
  454.  */
  455. #define    MACH_GET_CUR_STATE_PTR(reg1, reg2)        \
  456.     MACH_GET_CUR_PROC_PTR(reg1);            \
  457.         set     _machStatePtrOffset, reg2;        \
  458.         ld      [reg2], reg2;                \
  459.         add     reg1, reg2, reg1;            \
  460.         ld      [reg1], reg1
  461.  
  462. #endif /* _MACHASMDEFS */
  463.